/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.service.grant.department.impl;

import com.google.common.base.Splitter;
import com.je.common.base.DynaBean;
import com.je.common.base.service.MetaService;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.rbac.rpc.workflow.util.WorkFlowParserUserUtil;
import com.je.rbac.service.IconType;
import com.je.rbac.service.company.RbacDepartmentService;
import com.je.rbac.service.grant.department.RbacGrantDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class RbacGrantDepartmentServiceImpl implements RbacGrantDepartmentService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private RbacDepartmentService rbacDepartmentService;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public long removeDepartmetnAccountRole(String roleId, String departmentId, String accountId) {
        return metaService.delete("JE_RBAC_ACCOUNTROLE", ConditionsWrapper.builder()
                .eq("ACCOUNTROLE_ROLE_ID", roleId)
                .eq("ACCOUNTROLE_DEPT_ID", departmentId).eq("ACCOUNTROLE_ACCOUNT_ID", accountId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void removeDepartmentAccount(String departmentId, String accountId) {
        metaService.delete("JE_RBAC_ACCOUNTDEPT", ConditionsWrapper.builder()
                .eq("ACCOUNTDEPT_DEPT_ID", departmentId).eq("ACCOUNTDEPT_ACCOUNT_ID", accountId));
        metaService.delete("JE_RBAC_ACCOUNTROLE", ConditionsWrapper.builder()
                .eq("ACCOUNTROLE_DEPT_ID", departmentId)
                .eq("ACCOUNTROLE_ACCOUNT_ID", accountId));
    }

    @Override
    public JSONTreeNode buildCompanyDepartmentUserTree(Boolean multiple, String... companyIds) {
        JSONTreeNode companyNode = rbacDepartmentService.buildCompanyTreeData(false,companyIds);
        List<DynaBean> departmentUserBeanList;
        if (companyIds == null || companyIds.length <= 0) {
            departmentUserBeanList = metaService.select("JE_RBAC_VACCOUNTDEPT", ConditionsWrapper.builder());
        } else {
            departmentUserBeanList = metaService.select("JE_RBAC_VACCOUNTDEPT", ConditionsWrapper.builder().in("SY_COMPANY_ID", companyIds));
        }

        recursiveDepartmentUserTreeNode(companyNode, departmentUserBeanList, multiple);
        return companyNode;
    }

    @Override
    public JSONTreeNode buildCompanyDepartmentUserTreeAddOwn(Boolean multiple, Boolean addOwn,String userId, String... companyIds) {
        JSONTreeNode companyNode = rbacDepartmentService.buildCompanyTreeData(false,companyIds);
        List<DynaBean> departmentUserBeanList;
        ConditionsWrapper conditionsWrapper = ConditionsWrapper.builder();
        if (companyIds == null || companyIds.length <= 0) {
            if (!addOwn){
                 conditionsWrapper = ConditionsWrapper.builder().ne("JE_RBAC_ACCOUNTDEPT_ID", userId);
            }

            departmentUserBeanList = metaService.select("JE_RBAC_VACCOUNTDEPT", conditionsWrapper);
        } else {
            if (!addOwn){
                conditionsWrapper = ConditionsWrapper.builder().ne("JE_RBAC_ACCOUNTDEPT_ID", userId);
            }
            conditionsWrapper.in("SY_COMPANY_ID", companyIds);
            departmentUserBeanList = metaService.select("JE_RBAC_VACCOUNTDEPT", conditionsWrapper);
        }

        recursiveDepartmentUserTreeNode(companyNode, departmentUserBeanList, multiple);
        return companyNode;
    }

    private void recursiveDepartmentUserTreeNode(JSONTreeNode rootNode, List<DynaBean> departmentUserBeanList, Boolean multiple) {
        if ("department".equals(rootNode.getNodeInfoType())) {
            for (DynaBean eachDepartmentUserBean : departmentUserBeanList) {
                eachDepartmentUserBean.put("DEPARTMENT_ICON", IconType.TCONTYPE_ROLE.getVal());
                if (!rootNode.getId().equals(eachDepartmentUserBean.getStr("ACCOUNTDEPT_DEPT_ID"))) {
                    continue;
                }
                WorkFlowParserUserUtil.parseAccountDepartmentToTree(rootNode, eachDepartmentUserBean, multiple, true);
            }
        }

        if (rootNode.getChildren() == null || rootNode.getChildren().isEmpty()) {
            return;
        }

        for (JSONTreeNode eachChildNode : rootNode.getChildren()) {
            recursiveDepartmentUserTreeNode(eachChildNode, departmentUserBeanList, multiple);
        }
    }

    @Override
    public JSONTreeNode buildCompanyDepartmentUserOrgStrTree(String... companyIds) {
        JSONTreeNode companyNode = rbacDepartmentService.buildCompanyTreeData(false,companyIds);
        List<DynaBean> departmentUserBeanList;
        if (companyIds == null || companyIds.length <= 0) {
            departmentUserBeanList = metaService.select("JE_RBAC_VDEPTUSER", ConditionsWrapper.builder());
        } else {
            departmentUserBeanList = metaService.select("JE_RBAC_VDEPTUSER", ConditionsWrapper.builder().in("SY_COMPANY_ID", companyIds));
        }

        recursiveDepartmentUserOrgStrTreeNode(companyNode, departmentUserBeanList);
        return companyNode;
    }

    private void recursiveDepartmentUserOrgStrTreeNode(JSONTreeNode rootNode, List<DynaBean> departmentUserBeanList) {
        if ("department".equals(rootNode.getNodeInfoType())) {
            for (DynaBean eachDepartmentUserBean : departmentUserBeanList) {
                eachDepartmentUserBean.put("DEPARTMENT_ICON", IconType.TCONTYPE_ROLE.getVal());
                if (!rootNode.getId().equals(eachDepartmentUserBean.getStr("JE_RBAC_DEPARTMENT_ID"))) {
                    continue;
                }
                WorkFlowParserUserUtil.parseUserDepartmentToTree(rootNode, eachDepartmentUserBean);
            }
        }
        if (rootNode.getChildren() == null || rootNode.getChildren().isEmpty()) {
            return;
        }
        for (JSONTreeNode eachChildNode : rootNode.getChildren()) {
            recursiveDepartmentUserOrgStrTreeNode(eachChildNode, departmentUserBeanList);
        }
    }


    @Override
    public List<Map<String, Object>> findRoleUsers(String roleIds) {
        List<String> roleIdList = Splitter.on(",").splitToList(roleIds);
        List<DynaBean> roleAccountBeanList = metaService.select("JE_RBAC_VACCOUNTROLE", ConditionsWrapper.builder()
                .in("ACCOUNTROLE_ROLE_ID", roleIdList).orderByDesc("AR_SY_ORDERINDEX"));
        if (roleAccountBeanList.size() <= 0) {
            return new ArrayList<Map<String, Object>>();
        }
        Map<String, List<String>> deptUserIdMap = new HashMap<>();
        List<String> userIdList;
        for (DynaBean eachRoleAccountBean : roleAccountBeanList) {
            if (deptUserIdMap.containsKey(eachRoleAccountBean.getStr("ACCOUNTROLE_DEPT_ID"))) {
                userIdList = deptUserIdMap.get(eachRoleAccountBean.getStr("ACCOUNTROLE_DEPT_ID"));
            } else {
                userIdList = new ArrayList<>();
                deptUserIdMap.put(eachRoleAccountBean.getStr("ACCOUNTROLE_DEPT_ID"), userIdList);
            }
            userIdList.add(eachRoleAccountBean.getStr("USER_ASSOCIATION_ID"));
        }

        //查询
        ConditionsWrapper wrapper = ConditionsWrapper.builder().table("JE_RBAC_VDEPTUSER");
        int i = 0;
        for (Map.Entry<String, List<String>> eachEntry : deptUserIdMap.entrySet()) {
            if (i == 0) {
                wrapper.eq("JE_RBAC_DEPARTMENT_ID", eachEntry.getKey()).in("JE_RBAC_USER_ID", eachEntry.getValue());
            } else {
                wrapper.or(inWrapper -> {
                    inWrapper.eq("JE_RBAC_DEPARTMENT_ID", eachEntry.getKey()).in("JE_RBAC_USER_ID", eachEntry.getValue());
                });
            }
            i++;
        }

        List<Map<String,Object>> listUserMap =  metaService.selectSql(wrapper);
        for(Map<String,Object> eachUserDeptMap : listUserMap){
            for(DynaBean eachAccountRoleBean : roleAccountBeanList){
                if(eachUserDeptMap.get("JE_RBAC_DEPARTMENT_ID").equals(eachAccountRoleBean.getStr("ACCOUNTROLE_DEPT_ID")) &&
                        eachUserDeptMap.get("JE_RBAC_USER_ID").equals(eachAccountRoleBean.getStr("USER_ASSOCIATION_ID"))){
                    eachUserDeptMap.put("SY_ORDERINDEX",eachAccountRoleBean.getStr("AR_SY_ORDERINDEX"));
                }
            }
        }

        Collections.sort(listUserMap, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Integer name1 = 0;
                Integer name2 = 0;
                if(o1.get("SY_ORDERINDEX") != null && o2.get("SY_ORDERINDEX") !=null){
                     name1 = Integer.valueOf(o1.get("SY_ORDERINDEX").toString()) ;//name1是从你list里面拿出来的一个
                     name2 = Integer.valueOf(o2.get("SY_ORDERINDEX").toString()) ; //name1是从你list里面拿出来的第二个name
                }
                return name1.compareTo(name2);
            }
        });
        return listUserMap;
    }
}
